package org.quickbundle.project.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.texen.util.PropertiesUtil;

import com.dfhc.util.StringHelper;

public class FilterSql implements Filter {

	 private static final String CMD = "cmd";
	private static final String DELETE = "delete";
	private static final String UPDATE = "update";
	private static final String INSERT = "insert";
	private static final String ACTION = "action";
	private Pattern firstwp;
	/**
	 * 解决sql注入问题
	 * @param msg
	 * @return
	 */

	public void doFilter(ServletRequest servletrequest,
			ServletResponse servletresponse, FilterChain filterchain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		if(!checkSqlInjection(servletrequest)){
			HttpServletRequest req = (HttpServletRequest) servletrequest;
    		HttpServletResponse res = (HttpServletResponse) servletresponse;
//			request.getRequestDispatcher("/jsp/util/sqlInjectionNoPermission.jsp").forward(request, response);
			//res.sendRedirect(req.getContextPath() +  "/myplace/sqlInject.action");
			res.sendRedirect(req.getContextPath() +  "/jsp/util/sqlInjectionNoPermission.jsp");
			return;
		}
			  filterchain.doFilter(servletrequest, servletresponse);
	           
	       

	}

	/**
	 * 检查请求参数是否包含sql语句关键字
	 * @param request
	 * @return 存在sql注入，返回false;否则返回true;
	 */
	private boolean checkSqlInjection(ServletRequest request) {
		List<Object> paramValues = new ArrayList<Object>();
		if(request.getParameterMap().size()>0){
			Iterator itkey = request.getParameterMap().keySet().iterator();
			while(itkey.hasNext()){
				Object key = itkey.next();
				Object val = request.getParameterMap().get(key);
                if(ACTION.equals(key) && (INSERT.equals(val) || UPDATE.equals(val) || DELETE.equals(val))){
					continue;
				}
                
                if(CMD.equals(key)){
					continue;
				}
				//如果参数值为数组
				if(val.getClass().isArray()){
					String tmpArray[] = (String[]) val;
					for(String tmpStr:tmpArray){
						paramValues.add(tmpStr);
					}
				}else{
					paramValues.add(val);
				}
			}
		}
		//检查是否有:select,update,insert,delete,drop,create
		String tmp;
		for(Object paramValue:paramValues){
			if(paramValue!=null){
				if(paramValue instanceof String){
					tmp = ((String)paramValue).toLowerCase();
				}else{
					tmp = paramValue.toString().toLowerCase();
				}
				//排除参数影响
				int pos = tmp.indexOf("?");
				if(pos!=-1){
					tmp = tmp.substring(0, pos);
				}
				if(isExistsSqlKey(tmp)){
					HttpServletRequest req = (HttpServletRequest) request;
					System.out.println("sql 注入 uri:"+req.getRequestURI()+",参数:"+tmp);
					return false;
				}
				//for(String key:sqlKeys){
//					if(tmp.indexOf(key)>=0){
//						//排除/ctrl/${sqlKeys}/ 情况
//						if(!(tmp.endsWith(key) ||tmp.endsWith(key+"/"))){
//							HttpServletRequest req = (HttpServletRequest) request;
//							System.out.println("uri:"+req.getRequestURI()+",参数:"+tmp+",关键字:"+key);
//							return false;
//						}
//					}
					
				//}
			}
		}
		return true;
	}
	/**
	 * 判断是否存在sql 关键字
	 * @param checkStr
	 * @return
	 */
	private boolean isExistsSqlKey(String checkStr) {
		   String[] strChilds={UPDATE,INSERT,DELETE,"select","drop","create"};
		   String sql = checkStr;	
		   //字符串搜索子串，判断子串前后是否出现不可见字符或(或)
		   List<Object> retObjs = StringHelper.findInStrArray(0, sql, strChilds, false);
		   int pos = (Integer) retObjs.get(0);
		   int keyIndex = (Integer)retObjs.get(1);
		   int nextpos; 
		   if(pos>=0){
			   nextpos = pos+strChilds[keyIndex].length();
			   if(pos>0){
				   if(!StringHelper.isNotVisibleChar(sql.charAt(pos-1))&&sql.charAt(pos-1)!=')'&&sql.charAt(pos-1)!='('){
					     return false;
				   }else{
					   if(nextpos<sql.length()){
						   if(!StringHelper.isNotVisibleChar(sql.charAt(nextpos))&&sql.charAt(nextpos)!=')'&&sql.charAt(nextpos)!='('){
							   return false;
						   }else{
							   return true;
						   }
					   }else{
						   return true;
					   }
				   }
			   }else{
				   if(nextpos<sql.length()){
					   if(!StringHelper.isNotVisibleChar(sql.charAt(nextpos))&&sql.charAt(nextpos)!=')'&&sql.charAt(nextpos)!='('){
						   return false;
					   }else{
						   return true;
					   }
				   }else{
					   return true;
				   }
			   }
			   
		   }else{
			   return false;
		   }	   
	}

	public void init(FilterConfig filterconfig) throws ServletException {
		String firstRegex = "(.+)?([^a-zA-Z])?(update|insert|delete|select|drop|create)([^a-zA-Z])(.+)?";
		firstwp = Pattern.compile(firstRegex,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
	

	}
	public void destroy() {
		// TODO Auto-generated method stub
		

	}

}
